/* $Id:skill.cc $ */
/*
   Copyright (C) 2007 by Jurjen Stellingwerff <jurjen@stwerff.xs4all.nl>
   Part of the Moros Project http://moros.sourceforge.net/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 3.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

#define DEBUG_ROUTINE "skill"

#include <sstream>
#include <fstream>
#include "../general/util.h"
#include "../general/log.h"
#include "../general/channel.h"
#include "skill.h"
#include "background.h"
#include "../general/general.h"
#include "action.h"

skill::skill() {
    background=0;
    name="";
    description="";
    specials=map<string,class special>();
}

// Field : background

class background& skill::getBackground() const { if (background==0) throw nullpointer(); return *background; }
void skill::setBackground(class background &v) { background=&v; }

// Field : name

const string skill::getName() const { return name; }
void skill::setName(const string v) { name=v; }

// Field : description

const string skill::getDescription() const { return description; }
void skill::setDescription(const string v) { description=v; }

// Field : specials

class special& skill::getSpecials(const string v) { return specials[v]; }
map<string,class special>& skill::listSpecials() { return specials; }
void skill::setSpecials(class special &v) {
    if (v.getName()=="") throw unnamed();
    specials[v.getName()]=v;
}
void skill::delSpecials(const string v) { specials.erase(v); }
const bool skill::isSpecials(const string v) const { return specials.count(v)>0; }

void skill::save(class channel &ch) {
    ch.write("skill", "");
    ch.write("b", getBackground().getName());
    ch.write("n", getName());
    ch.write("d", getDescription());
    loopSkillSpecials(this, s_specials) {
        s_specials->save(ch);
    }
}

void skill::load(class channel &ch) {
    if (ch.key=="b" || ch.key=="background") {
        if (!background_repo.isBackground(ch.value)) {
            dbg_state("link unknown background %s", ch.value.c_str());
            class background rec;
            rec.setName(ch.value);
            background_repo.setBackground(rec);
            rec.setNr(0);
        }
        setBackground(background_repo.getBackground(ch.value));
        ch.next();
    }
    if (ch.key=="n" || ch.key=="name") { setName(ch.value); ch.next(); }
    if (ch.key=="d" || ch.key=="description") { setDescription(ch.value); ch.next(); }
    while (ch.key=="special" || ch.key=="specials") {
        ch.next();
        class special rec;
        rec.load(ch);
        setSpecials(rec);
        while (ch.key=="action" && ch.value=="") action_repo.load(ch);
    }
}

void skill::xml(ofstream &f, int l, int r) {
    f << ncpy(l, "  ") << "<skill name=\"" << xml_encode(getName()) <<
    "\" description=\"" << xml_encode(getDescription()) <<
    "\">" << endl;
    if (r<2) try {
        getBackground().xml(f,l+1,r+1);
    } catch (nullpointer n) {}
    if (r==0) {
        loopSkillSpecials(this, s_specials) {
            s_specials->xml(f,l+1);
        }
    }
    f << ncpy(l, "  ") << "</skill>" << endl;
}

// Repository

skillRepository skill_repo;

class skill& skillRepository::getSkill(const string v) { return skills[v]; }
void skillRepository::setSkill(class skill& v) {
    if (v.getName()=="") throw unnamed();
    skills[v.getName()]=v;
}
map<string,class skill>& skillRepository::listSkill() { return skills; }
void skillRepository::delSkill(const string v) { skills.erase(v); }
const bool skillRepository::isSkill(const string v) const { return skills.count(v)>0; }
void skillRepository::save(class channel &ch) {
    loopSkills(rec) {
        rec->save(ch);
    }
}

bool skillRepository::load(class channel &ch) {
    if (ch.key=="skill") {
        ch.next();
        class skill rec;
        rec.load(ch);
        setSkill(rec);
        return true;
    }
    return false;
}
